﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace System.Peppers.UI
{
    /// <summary>
    /// Size class, very similar to System.Drawing.Size
    /// </summary>
    [Serializable, StructLayout(LayoutKind.Sequential)]
    public struct Size
    {
        /// <summary>
        /// Empty instance
        /// </summary>
        public static readonly Size Empty = new Size();
        private int width;
        private int height;

        /// <summary>
        /// Ctor that takes a point
        /// </summary>
        /// <param name="pt">X == Width, Y == Height</param>
        public Size(Point pt)
        {
            this.width = pt.X;
            this.height = pt.Y;
        }

        /// <summary>
        /// Ctor that takes width/height
        /// </summary>
        /// <param name="width">width</param>
        /// <param name="height">height</param>
        public Size(int width, int height)
        {
            this.width = width;
            this.height = height;
        }

        /// <summary>
        /// Adds 2 sizes
        /// </summary>
        /// <param name="sz1">size 1</param>
        /// <param name="sz2">size 2</param>
        /// <returns>sizes summed</returns>
        public static Size operator +(Size sz1, Size sz2)
        {
            return new Size(sz1.Width + sz2.Width, sz1.Height + sz2.Height);
        }

        /// <summary>
        /// Subtracts a size from another
        /// </summary>
        /// <param name="sz1">size 1</param>
        /// <param name="sz2">size 2</param>
        /// <returns>sizes subtracted</returns>
        public static Size operator -(Size sz1, Size sz2)
        {
            return new Size(sz1.Width - sz2.Width, sz1.Height - sz2.Height);
        }

        /// <summary>
        /// Checks equality
        /// </summary>
        /// <param name="sz1">size 1</param>
        /// <param name="sz2">size 2</param>
        /// <returns>true if equal</returns>
        public static bool operator ==(Size sz1, Size sz2)
        {
            return ((sz1.Width == sz2.Width) && (sz1.Height == sz2.Height));
        }

        /// <summary>
        /// Checks equality
        /// </summary>
        /// <param name="sz1">size 1</param>
        /// <param name="sz2">size 2</param>
        /// <returns>true if not equal</returns>
        public static bool operator !=(Size sz1, Size sz2)
        {
            return !(sz1 == sz2);
        }

        /// <summary>
        /// Checks if width and height are non-zero
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return ((this.width == 0) && (this.height == 0));
            }
        }

        /// <summary>
        /// Width
        /// </summary>
        public int Width
        {
            get
            {
                return this.width;
            }
            set
            {
                this.width = value;
            }
        }

        /// <summary>
        /// Height
        /// </summary>
        public int Height
        {
            get
            {
                return this.height;
            }
            set
            {
                this.height = value;
            }
        }

        /// <summary>
        /// Checks if width/height are equal
        /// </summary>
        /// <param name="obj">Size object to compare</param>
        /// <returns>True if equal</returns>
        public override bool Equals(object obj)
        {
            if (!(obj is Size))
            {
                return false;
            }
            Size size = (Size)obj;
            return ((size.width == this.width) && (size.height == this.height));
        }

        /// <summary>
        /// Hashcode of struct
        /// </summary>
        /// <returns>width ^ height</returns>
        public override int GetHashCode()
        {
            return (this.width ^ this.height);
        }
    }
}